#include <string>
#include <cassert>
#include <sstream>
#include <iostream>

using namespace std;

class Rational
{
    int nume;  //numerator
    int deno;  //denominator cannot be zero
    friend int gcd(int m, int n);
    friend void reduce(int &n, int &d);
public:
    //constructor
    Rational(int n=0, int d=1);
    //arithmatic operations
    Rational operator+(const Rational& r)const;
    Rational operator-(const Rational& r)const;
    Rational operator*(const Rational& r)const;
    Rational operator/(const Rational& r)const;
    //conversion
    const Rational &operator=(double val);
    double toDouble()const;
    string toString()const;
    //prefix"++r", postfix "r++"
    const Rational &operator++();
    Rational operator++(int);
    //negative"-"
    Rational operator-()const;
    //">" and "<"
    friend bool operator>(const Rational &l, const Rational &r);
    friend bool operator<(const Rational &l, const Rational &r);
    //">>" and "<<"
    friend istream &operator>>(istream &in, Rational &r);
    friend ostream &operator<<(ostream &out, const Rational &r);
};

int gcd(int m, int n)
{
    int c = n;
    while (m%n!=0)
    {
        c = m%n;
        m = n;
        n = c;
    }
    return c;
}

void reduce(int &n, int &d)
{
    int g;

    assert(d!=0);

    if(n == 0)
    {
        n = 0;
        d = 1;
        return;
    }

    if (d<0)
    {
        d = -d;
        n = -n;
    }

    if (n<0)
        g = gcd(-n, d);
    else
        g = gcd(n, d);

    n = n/g;
    d = d/g;
}

Rational::Rational(int n, int d)
{
    nume = n;
    deno = d;
    reduce(nume, deno);
}

//arithmatic operations
Rational Rational::operator+(const Rational& r)const
{
    int d = deno * r.deno;
    int n = deno * r.nume + nume * r.deno;
    return Rational(n, d);
}

Rational Rational::operator-(const Rational& r)const
{
    int d = deno * r.deno;
    int n = nume * r.deno - deno * r.nume;
    return Rational(n, d);
}

Rational Rational::operator*(const Rational& r)const
{
    return Rational(nume * r.nume, deno * r.deno);
}

Rational Rational::operator/(const Rational& r)const
{
    return Rational(nume * r.deno, deno * r.nume);
}

string Rational::toString()const
{
    ostringstream ostr;

    if(nume == 0)
        ostr << 0;
    else if(deno == 1)
        ostr << nume;
    else
        ostr << nume << "/" << deno;

    return ostr.str();
}

double Rational::toDouble()const
{
    double d = static_cast<double>(nume)/deno;
    return d;
}

const Rational &Rational::operator=(double val)
{
    const double precision=1.0e-7;

    deno = (int)(1.0/precision);
    nume = (int)(val*deno);

    reduce(deno, nume);

    return *this;
}

//prefix"++r", ++n/d --> (n+d)/d
const Rational &Rational::operator++()
{
    nume = nume + deno;
    return *this;
}

//postfix "r++"
Rational Rational::operator++(int)
{
    Rational tmp = *this;
    nume = nume+deno;
    return tmp;
}

//negative"-"
Rational Rational::operator-()const
{
    return Rational(-nume, deno);
}

//">" and "<"
bool operator>(const Rational &l, const Rational &r)
{
    Rational d = l-r;
    return (d.nume>0);
}

bool operator<(const Rational &l, const Rational &r)
{
    Rational d = l-r;
    return (d.nume<0);
}

//">>" and "<<"
istream &operator>>(istream &in, Rational &r)
{
    in >> r.nume >> r.deno;
    return in;
}

ostream &operator<<(ostream &out, const Rational &r)
{
    string s = r.toString();
    out << s;
    return out;
}


int main()
{
    Rational r1;
    Rational r2(2, 1);
    Rational r3(-3, -4);
    Rational r4(3, -9);
    Rational r5;

    r1 = 3.6;
    r5 = -r4;
    r4++;
    ++r4;

    cout<<"r1: "<<r1<<endl;
    cout<<"r2: "<<r2<<endl;
    cout<<"r3: "<<r3<<endl;
    cout<<"r4: "<<r4<<endl;
    cout<<"r5: "<<r5<<endl;

    if (r4>r2)
        cout << "r4>r2" << endl;
    else
        cout <<"r4<r2" << endl;

    cout<<"r2+r3: "<<(r2+r3)<<endl;
    cout<<"r2-r3: "<<(r2-r3)<<endl;
    cout<<"r2*r3: "<<(r2*r3)<<endl;
    cout<<"r2/r3: "<<(r2/r3)<<endl;

    cout<<"r4+r3: "<<(r4+r3)<<endl;
    cout<<"r4-r3: "<<(r4-r3)<<endl;
    cout<<"r4*r3: "<<(r4*r3)<<endl;
    cout<<"r4/r3: "<<(r4/r3)<<endl;

    return 0;
}
